import { Injectable } from '@nestjs/common';

/**
 * 反射工具类
 * 基于 NestJS 实现 Java 风格的反射工具
 * 对应 Java: ReflectCallConstructor, ReflectCallMethod
 */
@Injectable()
export class ReflectUtil {
  /**
   * 根据类名获取类
   * @param className 类名
   * @returns 类构造函数
   */
  getClass<T = any>(className: string): new (...args: any[]) => T {
    try {
      // 在 Node.js 环境中，需要通过全局对象获取类
      const ClassConstructor = (global as any)[className];
      if (ClassConstructor && typeof ClassConstructor === 'function') {
        return ClassConstructor as new (...args: any[]) => T;
      }
      throw new Error(`Class ${className} not found`);
    } catch (error) {
      throw new Error(`Failed to get class ${className}: ${error.message}`);
    }
  }

  /**
   * 根据类名创建实例
   * @param className 类名
   * @returns 类实例
   */
  newInstance<T = any>(className: string): T {
    try {
      const ClassConstructor = this.getClass<T>(className);
      return new ClassConstructor();
    } catch (error) {
      throw new Error(
        `Failed to create instance of ${className}: ${error.message}`,
      );
    }
  }

  /**
   * 根据类名和参数创建实例
   * @param className 类名
   * @param args 构造参数
   * @returns 类实例
   */
  newInstanceWithArgs<T = any>(className: string, ...args: any[]): T {
    try {
      const ClassConstructor = this.getClass<T>(className);
      return new ClassConstructor(...args);
    } catch (error) {
      throw new Error(
        `Failed to create instance of ${className} with args: ${error.message}`,
      );
    }
  }

  /**
   * 调用静态方法
   * @param className 类名
   * @param methodName 方法名
   * @param args 方法参数
   * @returns 方法返回值
   */
  invokeStaticMethod<T = any>(
    className: string,
    methodName: string,
    ...args: any[]
  ): T {
    try {
      const ClassConstructor = this.getClass(className);
      if (typeof ClassConstructor[methodName] === 'function') {
        return ClassConstructor[methodName](...args);
      }
      throw new Error(
        `Static method ${methodName} not found in class ${className}`,
      );
    } catch (error) {
      throw new Error(
        `Failed to invoke static method ${className}.${methodName}: ${error.message}`,
      );
    }
  }

  /**
   * 调用实例方法
   * @param instance 实例对象
   * @param methodName 方法名
   * @param args 方法参数
   * @returns 方法返回值
   */
  invokeMethod<T = any>(instance: any, methodName: string, ...args: any[]): T {
    try {
      if (instance && typeof instance[methodName] === 'function') {
        return instance[methodName](...args);
      }
      throw new Error(`Method ${methodName} not found in instance`);
    } catch (error) {
      throw new Error(
        `Failed to invoke method ${methodName}: ${error.message}`,
      );
    }
  }

  /**
   * 设置对象属性值
   * @param target 目标对象
   * @param fieldName 属性名
   * @param value 属性值
   */
  setFieldValue(target: any, fieldName: string, value: any): void {
    try {
      if (target && typeof target === 'object') {
        target[fieldName] = value;
      } else {
        throw new Error('Target is not a valid object');
      }
    } catch (error) {
      throw new Error(`Failed to set field ${fieldName}: ${error.message}`);
    }
  }

  /**
   * 获取对象属性值
   * @param target 目标对象
   * @param fieldName 属性名
   * @returns 属性值
   */
  getFieldValue<T = any>(target: any, fieldName: string): T {
    try {
      if (target && typeof target === 'object') {
        return target[fieldName];
      }
      throw new Error('Target is not a valid object');
    } catch (error) {
      throw new Error(`Failed to get field ${fieldName}: ${error.message}`);
    }
  }

  /**
   * 检查对象是否有指定方法
   * @param target 目标对象
   * @param methodName 方法名
   * @returns 是否有该方法
   */
  hasMethod(target: any, methodName: string): boolean {
    return (
      target &&
      typeof target === 'object' &&
      typeof target[methodName] === 'function'
    );
  }

  /**
   * 检查对象是否有指定属性
   * @param target 目标对象
   * @param fieldName 属性名
   * @returns 是否有该属性
   */
  hasField(target: any, fieldName: string): boolean {
    return target && typeof target === 'object' && fieldName in target;
  }

  /**
   * 获取对象的所有方法名
   * @param target 目标对象
   * @returns 方法名数组
   */
  getMethodNames(target: any): string[] {
    if (!target || typeof target !== 'object') {
      return [];
    }
    return Object.getOwnPropertyNames(target).filter(
      (name) => typeof target[name] === 'function',
    );
  }

  /**
   * 获取对象的所有属性名
   * @param target 目标对象
   * @returns 属性名数组
   */
  getFieldNames(target: any): string[] {
    if (!target || typeof target !== 'object') {
      return [];
    }
    return Object.getOwnPropertyNames(target).filter(
      (name) => typeof target[name] !== 'function',
    );
  }

  /**
   * 复制对象属性
   * @param source 源对象
   * @param target 目标对象
   * @param fields 要复制的属性名数组，不指定则复制所有属性
   */
  copyFields(source: any, target: any, fields?: string[]): void {
    try {
      if (
        !source ||
        !target ||
        typeof source !== 'object' ||
        typeof target !== 'object'
      ) {
        throw new Error('Source and target must be valid objects');
      }

      const fieldsToCopy = fields || Object.getOwnPropertyNames(source);
      fieldsToCopy.forEach((fieldName) => {
        if (source.hasOwnProperty(fieldName)) {
          target[fieldName] = source[fieldName];
        }
      });
    } catch (error) {
      throw new Error(`Failed to copy fields: ${error.message}`);
    }
  }

  /**
   * 检查对象是否为空
   * @param obj 要检查的对象
   * @returns 是否为空
   */
  isEmpty(obj: any): boolean {
    if (obj === null || obj === undefined) {
      return true;
    }

    if (typeof obj === 'string') {
      return obj.length === 0;
    }

    if (Array.isArray(obj)) {
      return obj.length === 0;
    }

    if (typeof obj === 'object') {
      return Object.keys(obj).length === 0;
    }

    return false;
  }

  /**
   * 检查对象是否不为空
   * @param obj 要检查的对象
   * @returns 是否不为空
   */
  isNotEmpty(obj: any): boolean {
    return !this.isEmpty(obj);
  }
}
